from abc import ABC, abstractmethod
from typing import Dict, Any, List
from datetime import datetime
import os

from ..core.base_reporter import ReporterError
from ..services.base_service_handler import ServiceHandlerFactory

class BaseFormatter(ABC):
    """报告格式化器基类"""
    
    def __init__(self, output_dir: str):
        """初始化格式化器
        
        Args:
            output_dir: 输出目录路径
        """
        self.output_dir = output_dir
        self.service_factory = ServiceHandlerFactory()
    
    @abstractmethod
    def format_report(self, results: List[Dict[str, Any]], scan_info: Dict[str, Any]) -> None:
        """格式化报告的抽象方法
        
        Args:
            results: 扫描结果列表
            scan_info: 扫描信息字典
        """
        pass
    
    def _safe_str(self, value: Any) -> str:
        """安全地将值转换为字符串
        
        Args:
            value: 要转换的值
            
        Returns:
            str: 转换后的字符串
        """
        if value is None:
            return ''
        return str(value).replace('<', '&lt;').replace('>', '&gt;')
    
    def _format_timestamp(self, timestamp: float) -> str:
        """格式化时间戳
        
        Args:
            timestamp: Unix时间戳
            
        Returns:
            str: 格式化的时间字符串
        """
        try:
            return datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
        except (TypeError, ValueError):
            return 'N/A'
    
    def _get_service_details(self, service_info: Dict[str, Any]) -> List[str]:
        """获取服务详细信息
        
        Args:
            service_info: 服务信息字典
            
        Returns:
            List[str]: 服务详细信息列表
        """
        if not service_info:
            return []
            
        service_type = service_info.get('name', '')
        handler = self.service_factory.get_handler(service_type)
        return handler.get_service_details(service_info)
    
    def _write_file(self, filename: str, content: str, mode: str = 'w', encoding: str = 'utf-8') -> None:
        """安全地写入文件
        
        Args:
            filename: 文件名
            content: 要写入的内容
            mode: 写入模式
            encoding: 文件编码
            
        Raises:
            ReporterError: 当写入文件失败时
        """
        try:
            with open(filename, mode, encoding=encoding) as f:
                f.write(content)
        except OSError as e:
            raise ReporterError(f"写入文件 {filename} 时发生错误: {str(e)}")
    
    def _get_status_style(self, status: str) -> tuple:
        """获取状态对应的样式
        
        Args:
            status: 端口状态
            
        Returns:
            tuple: (状态文本, 状态样式类)
        """
        status_map = {
            'open': ('开放', 'status open'),
            'closed': ('关闭', 'status closed'),
            'filtered': ('被过滤', 'status filtered')
        }
        return status_map.get(status, (status, 'status')) 